package com.chen.back.controller;

import cn.hutool.core.lang.UUID;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chen.back.entity.*;
import com.chen.back.mapper.UserMapper;
import com.chen.back.redis.CustomRedisManager;
import com.chen.back.response.Result;
import com.chen.back.service.ChooseCourseService;
import com.chen.back.service.RoleService;
import com.chen.back.service.UserRoleService;
import com.chen.back.service.UserService;
import com.chen.back.token.JwtToken1;
import com.chen.back.util.JwtUtil;
import com.chen.back.util.StringUtil;
import com.google.code.kaptcha.Producer;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.redisson.api.RLock;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.*;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author chen
 * @since 2022-02-24
 */
@RestController
@RequestMapping("/user")
public class UserController extends BaseController{
    @Autowired
    Producer producer;
    @Autowired
    CustomRedisManager customRedisManager;
    @Autowired
    private UserService userService;
    @Autowired
    private RoleService roleService;
    @Autowired
    private UserRoleService userRoleService;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private ChooseCourseService chooseCourseService;
    @Autowired
    private RedissonClient redisson;
@CrossOrigin
//@RequiresPermissions("course:choose")
    @RequestMapping(value = "/test",method = RequestMethod.GET)
    public String test()
    {
        return "你好世界";
    }



    @GetMapping("/captcha")
    public String captcha() throws IOException {
        System.out.println("生成验证码");
        String key = UUID.randomUUID().toString();
        String code = producer.createText();
        System.out.println("后端生成的"+code);
        System.out.println("后端生成的"+key);

        // 为了测试
//        key = "aaaaa";
//        code = "11111";

        BufferedImage image = producer.createImage(code);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ImageIO.write(image, "jpg", outputStream);

        BASE64Encoder encoder = new BASE64Encoder();
        String str = "data:image/jpeg;base64,";

        String base64Img = str + encoder.encode(outputStream.toByteArray());

        RReadWriteLock writer = redisson.getReadWriteLock("writerRead");
        RLock rLock = writer.writeLock();
        try{
            rLock.lock();
            customRedisManager.hset("captcha", key, code, 120);
        }catch (Exception e)
        {
            e.printStackTrace();
        }finally {
            rLock.unlock();
        }


        System.out.println("从Redis中获取"+customRedisManager.hget("captcha",key));
        return JSON.toJSONString(new Result().setCode(200).setMessage("登录成功").setData(MapUtil.builder()
                .put("token", key)
                .put("captchaImg", base64Img)
                .build()));

    }
    @ApiOperation("登录")
    @RequestMapping(value = "/login",method = RequestMethod.POST)
    public String login(@RequestBody User user,String code,String key)
    {
//        System.out.println("前端的验证码："+code);
        System.out.println("前端的key："+key);
        RReadWriteLock read = redisson.getReadWriteLock("writerRead");
        RLock readLock = read.readLock();
        String hget="";
        try{
            readLock.lock();
             hget = (String)customRedisManager.hget("captcha", key);
        }catch (Exception e)
        {
            e.printStackTrace();
        }finally {
            readLock.unlock();
        }

        System.out.println("存贮在Redis中验证码："+hget);
        if (hget==null)
        {
            System.out.println("redis失败了");
            return JSON.toJSONString(new Result().setCode(401).setMessage("验证码错误"));

        }
        else if (user.getUsername() == null || user.getPassword() == null) {
            return JSON.toJSONString(new Result().setCode(500).setMessage("账号密码不能为空"));
        }
        Subject subject = SecurityUtils.getSubject();
        String token = JwtUtil.createJWT(user.getUsername(), "back", "user", 1000 * 60 * 60 * 24);
        JwtToken1 jwtToken = new JwtToken1(token, user.getPassword());
        try {
            subject.login(jwtToken);
        }catch (UnknownAccountException e) {
            return JSON.toJSONString(new Result().setCode(401).setMessage("账号不存在"));
        } catch (IncorrectCredentialsException e) {
            return JSON.toJSONString(new Result().setCode(402).setMessage("密码错误"));
        }
        //接下来是上述登录成功的操作

        User backUser = userService.getUserByUsername(user.getUsername());
        Map<String, Object> map = new HashMap<>();
        map.put("user", backUser);
        map.put("token", token);
        return JSON.toJSONString(new Result().setCode(200).setMessage("登录成功").setData(map));
    }
//主页面框架，是根据自己的权限生成栏框的
    @RequestMapping(value = "/getMenuList", method = RequestMethod.GET)
    public String getMenuList(String username) {
        if (StringUtils.isEmpty(username)) {
            return JSON.toJSONString(new Result().setCode(401).setMessage("未登录,请先登录"));
        }
        List<Map<String, Object>> list = userService.getMenuList(username);
        if (list == null) {
            return JSON.toJSONString(new Result().setCode(500).setMessage("获取错误"));
        } else {
            return JSON.toJSONString(new Result().setCode(200).setMessage("获取成功").setData(list));
        }
    }
    //@RequiresPermissions是shiro中访问权限管理
//@Nullable是可以所代表字符串为空
//StringUtils.isBlank返回字符串相反的结果
    @ApiOperation("查看学生名单")
    @RequiresPermissions("person:look")
    @RequestMapping(value = "/lookPerson", method = RequestMethod.GET)
    public String getPerson(@Nullable String username, @Nullable String roleName, @Nullable String pageNum, @Nullable String pageSize) {
        if (StringUtils.isBlank(username)) {
            username = null;
        }
        if (StringUtils.isBlank(roleName)) {
            roleName = null;
        }
        Integer first = StringUtil.changeString(pageNum);//字符串转为整数
        Integer second = StringUtil.changeString(pageSize);
//其实就是按照用户名找人
        Map<String, Object> list = userService.lookPerson(username, roleName, first, second);
        System.out.println(list);
        return JSON.toJSONString(new Result().setCode(200).setMessage("成功").setData(list));
    }
    @ApiOperation("获取学院所有老师")
    @RequestMapping(value = "/getTeachers", method = RequestMethod.GET)
    public String getTeachersBySchoolId(Integer schoolId) {
        List<User> list = userService.getAllTeachersBySchoolId(schoolId);
        return JSON.toJSONString(new Result().setCode(200).setData(list));
    }


    @ApiOperation("用户注册")
//    @RequiresPermissions("user:add")
    @RequestMapping(value = "/add",method = RequestMethod.POST)
//    @RequestBody将传过来的数据封装成对象的形式

    public String addUser(@RequestBody User user,Integer roleId){
        User user1 = new User();
    String s=StringUtil.generateUUID();
        user1.setUsername(user.getUsername());
        user1.setPassword(StringUtil.md5(user.getPassword()+s));
        user1.setSalt(s);
        user1.setSchoolId(1);
        user1.setNickname(user.getNickname());
        userService.saveOrUpdate(user1);
        UserRole userRole = new UserRole();
        userRole.setUserId(user1.getUserId());
        userRole.setRoleId(roleId);

       userRoleService.saveUserRole(userRole);
        return JSON.toJSONString(new Result().setCode(200).setMessage("注册成功"));
    }


    @ApiOperation("个人信息修改")
//    @RequiresPermissions("user:update")
    @RequestMapping(value = "/update", method = RequestMethod.POST)
    public String updateUser(@RequestBody  User user){
        User userByUsername = userService.getUserByUsername(user.getUsername());
        if (user.getPassword()!=userByUsername.getPassword()) {
            userByUsername.setPassword(StringUtil.md5(user.getPassword() + user.getSalt()));
        }

        user.setSalt(userByUsername.getSalt());
        userService.saveOrUpdate(user);

        return JSON.toJSONString(new Result().setCode(200).setMessage("success"));
    }

    @ApiOperation("个人密码修改")
//    @RequiresPermissions("user:update")
    @RequestMapping(value = "/updatePass", method = RequestMethod.POST)
    public String updatePass(@RequestBody PassVO passVO,String username){
        User userByUsername = userService.getUserByUsername(username);
        String password = userByUsername.getPassword();
        String salt = userByUsername.getSalt();
        String currentPass = passVO.getCurrentPass();
        String s = StringUtil.md5(passVO.getCurrentPass() + salt);
        boolean t=password.equals(s);

        if(!t)
        {
            return JSON.toJSONString(new Result().setCode(200).setMessage("原密码不正确"));

        }

        userByUsername.setPassword(StringUtil.md5(passVO.getPassWord()+salt));


        userService.saveOrUpdate(userByUsername);

        return JSON.toJSONString(new Result().setCode(200).setMessage("success"));
    }


    @ApiOperation("查看个人信息")
    @RequestMapping(value = "/look", method = RequestMethod.GET)
    public String lookUser( String username){
        Subject subject = SecurityUtils.getSubject();

        User userByUsername = userService.getUserByUsername(username);



        return JSON.toJSONString(new Result().setCode(200).setData(userByUsername));
    }

    @GetMapping("/info/{userId}")
    public String info(@PathVariable("userId") Integer userId) {

        System.out.println(userId);
        User user = userService.getById(userId);
        Assert.notNull(user, "找不到该管理员");

        List<Role> roles = roleService.listRolesByUserId(userId);


        user.setRoles(roles);
        for (Role r:user.getRoles()
             ) {
            System.out.println(r.getRoleName());
        }
        return JSON.toJSONString(new Result().setCode(200).setData(user));

    }

    @GetMapping("/list")
    public String list(String nickname) {
        System.out.println("搜索的名称"+nickname);
        Page<User> pageData = userService.page(getPage(), new QueryWrapper<User>()
                .like(StrUtil.isNotBlank(nickname), "nickname", nickname));

        pageData.getRecords().forEach(u -> {

            u.setRoles(roleService.listRolesByUserId(u.getUserId()));
        });
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.like(StrUtil.isNotBlank(nickname), "nickname", nickname);

        Integer total = userMapper.selectCount(wrapper);
        pageData.setTotal(total);
        return JSON.toJSONString(new Result().setCode(200).setData(pageData));

    }

    @PostMapping("/delete")
    public String delete(@RequestBody Integer[] ids) {

        userService.removeByIds(Arrays.asList(ids));
        userRoleService.remove(new QueryWrapper<UserRole>().in("user_id", ids));
        chooseCourseService.remove(new QueryWrapper<ChooseCourse>().in("user_id", ids));

        return JSON.toJSONString(new Result().setCode(200).setData("删除成功"));

    }

    @PostMapping("/role/{userId}")
    public Result rolePerm(@PathVariable("userId") Integer userId, @RequestBody Integer[] roleIds) {

        List<UserRole> userRoles = new ArrayList<>();

        Arrays.stream(roleIds).forEach(r -> {
            UserRole userRole = new UserRole();
            userRole.setRoleId(r);
            userRole.setUserId(userId);

            userRoles.add(userRole);
        });

        userRoleService.remove(new QueryWrapper<UserRole>().eq("user_id", userId));
chooseCourseService.remove(new QueryWrapper<ChooseCourse>().eq("user_id", userId));
        userRoleService.saveBatch(userRoles);



        return Result.succ("");
    }

}
